package com.example.lostandfoundsystem.web;

import com.example.lostandfoundsystem.web.middleware.AuthAdminPermissionMiddleware;
import com.example.lostandfoundsystem.web.middleware.AuthenticateLoadMiddleware;
import com.example.lostandfoundsystem.web.middleware.AuthenticateMiddleware;
import com.example.lostandfoundsystem.web.middleware.BaseMiddleware;
import com.example.lostandfoundsystem.models.system.User;
import com.example.lostandfoundsystem.models.system.Admin;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.*;

/**
 * @author lucifer
 * @since 2024-07-26-17:36
 */
@Configuration
public class Kernel implements WebMvcConfigurer {
    // 用于映射中间件和中间件别名的map
    private Map<String, HandlerInterceptor> middlewareList = new HashMap<>();

    {
        // 对象启动代码块
        // 基础拦截器
        middlewareList.put("base", new BaseMiddleware());
        // 用户装载拦截器
        middlewareList.put("auth.load", new AuthenticateLoadMiddleware());
        // 没有用户就返回401
        middlewareList.put("auth.user", new AuthenticateMiddleware(User.class));
        // 没有管理员就返回401
        middlewareList.put("auth.admin", new AuthenticateMiddleware(Admin.class));
        // 没有权限就返回403
        middlewareList.put("auth.admin.permission", new AuthAdminPermissionMiddleware());
    }

    // 基础中间件，所有都要加
    public List<String> baseMiddleware = new ArrayList<>();

    {
        baseMiddleware.add("base");
        baseMiddleware.add("auth.load");
    }

    // 分类中间件，只带部分去重功能
    public Map<String[], String[]> routeMiddleware = new LinkedHashMap<>();

    {
        //第一个参数是用来标记哪些路由要加，第二个参数是用来标记加哪些中间件，系统会自动装载
        //routeMiddleware.put(new String[]{"/admin/**", "!/admin/login"}, new String[]{"auth.admin", "auth.admin.permission"});
        //routeMiddleware.put(new String[]{"/user/**", "!/user/login"}, new String[]{"auth.user"});
    }


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        autoLoadInterceptors(registry);
    }

    private void autoLoadInterceptors(InterceptorRegistry registry) {
        // 创建一个map，用于标记中间件映射到的路由
        Map<String, List<String>> routeMiddlewareList = new LinkedHashMap<>();

        // 加入基础中间件
        for (String middlewareName : baseMiddleware) {
            // 基础路由
            if (middlewareList.containsKey(middlewareName) && middlewareList.get(middlewareName) != null) {
                registry.addInterceptor(middlewareList.get(middlewareName));
                // 给基础路由加入null，说明这个中间件不允许映射（containsKey存在，get为null）
                routeMiddlewareList.put(middlewareName, null);
            }
        }
        // 加入路由中间件
        routeMiddleware.forEach((key, value) -> {
            for (String middlewareName : value) {
                // 中间件的名字
                if (routeMiddlewareList.containsKey(middlewareName)) {
                    // 如果存在这个键，并且获取出来不是空
                    if (routeMiddlewareList.get(middlewareName) != null) {

                    } else {
                        // 如果获取出来是空，说明是基础中间件排除掉的，直接忽略
                        continue;
                    }
                } else {
                    // 否则，没有这个键，新建这个键
                    routeMiddlewareList.put(middlewareName, new ArrayList<>());
                }
                // 把路由数组加进去
                routeMiddlewareList.get(middlewareName).addAll(Arrays.asList(key));
            }
        });
        // 然后，根据map去进行中间件配置操作
        routeMiddlewareList.forEach((middlewareName, routeGroup) -> {
            if (routeGroup != null) {
                // 创建拦截器
                InterceptorRegistration interceptorRegistration = registry.addInterceptor(middlewareList.get(middlewareName));
                // 默认排除
                interceptorRegistration
                        .excludePathPatterns("/")
                        .excludePathPatterns("/index.html")
                        .excludePathPatterns("/static/**")
                        .excludePathPatterns("/js/**")
                        .excludePathPatterns("/css/**")
                        .excludePathPatterns("/fonts/**")
                        .excludePathPatterns("/img/**");

                for (String path : routeGroup) {
                    // 循环每个path
                    // 如果这个String的开头是包含!，代表这个是排除路由，否则是包含路由。
                    if (path.charAt(0) == '!') {
                        interceptorRegistration.excludePathPatterns(path.substring(1));
                    } else {
                        interceptorRegistration.addPathPatterns(path);
                    }
                }
            }
        });
    }
}
